#include "Filter.h"

#ifndef _countof
  #define _countof(array) (sizeof(array) / sizeof(array[0]))
#endif

void CFilterAdapter::Expose(void)
{
  py::class_<CHtmlFilter, boost::noncopyable>("HtmlFilter", py::no_init)
    .def("register", &CHtmlFilter::Register)
    .def("apply", &CHtmlFilter::Apply)
    ;

  py::class_<CFilterAdapter, py::bases<CHtmlFilter>, boost::noncopyable>("HtmlFilterAdapter", py::no_init)
    .def(py::init<CParser&, py::object, const std::string&>(py::args("parser", "handler", "name")))

    .add_property("handler", &CFilterAdapter::GetHandler)
    .add_property("name", &CFilterAdapter::GetName)
    ;

  py::class_<CDropTagFilter, py::bases<CHtmlFilter>, boost::noncopyable>("HtmlDropTagFilter", py::no_init)
    .add_property("name", &CDropTagFilter::GetName)
    ;

  py::class_<CWriterFilter, boost::noncopyable>("HtmlWriterFilter", py::no_init)
    .def(py::init<CParser&, py::object>(py::args("parser", "writer")))

    .def("register", &CWriterFilter::Register)
    .def("apply", &CWriterFilter::Apply)
    ;
}

CFilterAdapter::CFilterAdapter(CParser& parser, py::object handler, const std::string& name)
  : CHtmlFilter(parser), m_handler(handler), m_name(name)
{
  FillUpCallbacks();
}

void CFilterAdapter::FillUpCallbacks(void)
{
  static const char *CallbackNames[] = {
    "handle_startdoc",
    "handle_endoc",
    "handle_starttag",
    "handle_endtag",
    "handle_cdata",
    "handle_comment",
    "handle_decl",
    "handle_ie_decl",
    "handle_data",
    "flush"
  };

  for (size_t i=0; i<_countof(CallbackNames); i++)
  {
    const char *name = CallbackNames[i];

    if (::PyObject_HasAttrString(m_handler.ptr(), name))
    {
      py::object callback = m_handler.attr(name);

      if (::PyCallable_Check(callback.ptr()))
      {
        m_callbacks[name] = callback;
      }      
    }
  }
}